package com.softdev.system.generator.controller;

import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.softdev.system.generator.entity.ClassInfo;
import com.softdev.system.generator.entity.FieldInfo;
import com.softdev.system.generator.entity.ParamInfo;
import com.softdev.system.generator.service.GeneratorService;
import com.softdev.system.generator.service.GeneratorServiceImpl;
import com.softdev.system.generator.util.MapUtil;
import com.softdev.system.generator.util.TableParseUtil;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.softdev.system.generator.util.StringUtils;

/**
 * 代码生成控制器
 *
 * @author <a href="https://www.devtool.com/java.html">...</a>
 */

public class GeneratorController {

    private final GeneratorService generatorService = new GeneratorServiceImpl();

    /**
     * 生成代码
     *
     * @param dbDir 路径
     * @param type  类型
     * @param sql   sql
     * @return 代码
     */
    public String generateCode(String dbDir, String type, String sql) throws Exception {
        dbDir += "/code-generator/";
        switch (type) {
            case "index":
                return generateIndex(dbDir, type, sql).toString();
            case "procedure":
                type = "procedure-ui;proccontroller";
                return generateProcAndFun(dbDir, type, sql).toString();
            case "function":
                type = "function-ui;funcontroller";
                return generateProcAndFun(dbDir, type, sql).toString();
            case "view":
                type = "dot-entity;entity;jpacontroller;repository;view-list";
                break;
            case "table":
                type = "dot-entity;entity;jpacontroller;repository;layui-edit;layui-list";
                break;
        }
        ParamInfo paramInfo = new ParamInfo();
        if (StringUtils.isEmpty(sql)) {
            sql = "create table aa(id int ,aaa text)";
        }
        paramInfo.setTableSql(sql);
        HashMap<String, Object> map = new HashMap<>();
        String tmp = sql.toUpperCase();
        if (tmp.contains("CREATE OR REPLACE VIEW ") || tmp.contains("CREATE VIEW ")) {
            map.put("dataType", "view");
        } else if (tmp.contains("CREATE OR REPLACE FUNCTION ") || tmp.contains("CREATE FUNCTION ")) {
            map.put("dataType", "function");
        } else if (tmp.contains("CREATE OR REPLACE PROCEDURE ") || tmp.contains("CREATE PROCEDURE ")) {
            map.put("dataType", "procedure");
        } else if (tmp.contains("INSERT INTO ")) {
            map.put("dataType", "insert-sql");
        } else {
            map.put("dataType", "sql");
        }
        map.put("authorName", "llmdb");
        map.put("packageName", "com.itheima.layuidemo");
        map.put("returnUtilSuccess", "ReturnT.success");
        map.put("returnUtilFailure", "ReturnT.error");
        map.put("isPackageType", true);
        map.put("isSwagger", false);
        map.put("isAutoImport", true);
        map.put("isWithPackage", true);
        map.put("isComment", true);
        map.put("isLombok", true);
        map.put("ignorePrefix", "sys_");
        map.put("tinyintTransType", "int");
        map.put("nameCaseType", "CamelCase");
        map.put("timeTransType", "Date");
        paramInfo.setOptions(map);
        return generateCode(dbDir, type, paramInfo).toString();
    }

    /**
     * 生成index页面
     *
     * @param dbDir 文件夹
     * @param type  类型
     * @param name  页面
     * @return 返回值
     * @throws Exception 异常
     */
    private JSONObject generateProcAndFun(String dbDir, String type, String name) throws Exception {
        String[] stringArray = name.split(";");
        String tabName = stringArray[0];
        String param = null;
        if (stringArray.length > 1) {
            param = stringArray[1];
        }
        ParamInfo paramInfo = new ParamInfo();
        HashMap<String, Object> map = new HashMap<>();
        ClassInfo classInfo = new ClassInfo();
        String className = com.softdev.system.generator.util.StringUtils.upperCaseFirst(com.softdev.system.generator.util.StringUtils.underlineToCamelCase(tabName));
        classInfo.setClassName(className);
        classInfo.setTableName(tabName);
        map.put("tableName", className);
        map.put("classInfo", classInfo);
        classInfo.setFieldList(getParam(param));

        map.put("authorName", "llmdb");
        map.put("packageName", "com.itheima.layuidemo");
        map.put("returnUtilSuccess", "ReturnT.success");
        map.put("returnUtilFailure", "ReturnT.error");
        map.put("isPackageType", true);
        map.put("isSwagger", false);
        map.put("isAutoImport", true);
        map.put("isWithPackage", true);
        map.put("isComment", true);
        map.put("isLombok", true);
        map.put("ignorePrefix", "sys_");
        map.put("tinyintTransType", "int");
        map.put("nameCaseType", "CamelCase");
        map.put("timeTransType", "Date");
        paramInfo.setOptions(map);
        Map<String, String> result = generatorService.getResultByParams(dbDir, type, paramInfo.getOptions());
        result.put("className", classInfo.getClassName());
        return new JSONObject(result);
    }

    /**
     * 把参数转成json
     *
     * @param input 字符串
     * @return json对象
     */
    private List<FieldInfo> getParam(String input) {
        List<FieldInfo> fieldList = new ArrayList<>();
        if (StringUtils.isEmpty(input)) {
            return fieldList;
        }
        // 分割字符串以获取每个部分
        String[] parts = input.split(",");
        // 遍历每个部分并解析
        for (String part : parts) {
            String[] subParts = part.trim().split(" ");
            FieldInfo fd = new FieldInfo();
            String type;
            int index = 0;
            String inputType = subParts[0].toUpperCase();
            if ("IN".equals(inputType) || "OUT".equals(inputType)) {
                fd.setFieldName(inputType);
                index++;
            } else {
                fd.setFieldName("IN");
            }
            fd.setColumnName(subParts[index]);
            index++;
            type = subParts[index];
            index++;
            if (index < subParts.length) {
                type += subParts[index];
            }
            fd.setFieldComment(type);
            fieldList.add(fd);
        }
        return fieldList;
    }

    /**
     * 生成index页面
     *
     * @param dbDir 文件夹
     * @param type  类型
     * @param pages 页面
     * @return 返回值
     * @throws Exception 异常
     */
    private JSONObject generateIndex(String dbDir, String type, String pages) throws Exception {
        ParamInfo paramInfo = new ParamInfo();
        HashMap<String, Object> map = new HashMap<>();
        ClassInfo classInfo = new ClassInfo();
        String[] stringArray = pages.split(";");
        List<FieldInfo> fieldList = new ArrayList<>();
        for (String s : stringArray) {
            FieldInfo fd = new FieldInfo();
            fd.setFieldName(s);
            fieldList.add(fd);
        }
        classInfo.setFieldList(fieldList);
        map.put("classInfo", classInfo);
        map.put("tableName", "index");
        paramInfo.setOptions(map);
        Map<String, String> result = generatorService.getResultByParams(dbDir, type, paramInfo.getOptions());
        result.put("className", classInfo.getClassName());
        return new JSONObject(result);
    }

    private JSONObject generateCode(String dbDir, String type, ParamInfo paramInfo) throws Exception {
        //1.Parse Table Structure 表结构解析
        ClassInfo classInfo;
        String dataType = MapUtil.getString(paramInfo.getOptions(), "dataType");
        switch (dataType) {
            case "view":
                classInfo = TableParseUtil.processViewIntoClassInfo(paramInfo);
                break;
            case "insert-sql":
                classInfo = TableParseUtil.processInsertSqlToClassInfo(paramInfo);
                break;
            case "sql-regex":
                classInfo = TableParseUtil.processTableToClassInfoByRegex(paramInfo);
                break;
            default:
                classInfo = TableParseUtil.processTableIntoClassInfo(paramInfo);
                break;
        }

        //2.Set the params 设置表格参数

        paramInfo.getOptions().put("classInfo", classInfo);
        paramInfo.getOptions().put("tableName", classInfo.getTableName());
        //log the generated table and filed size记录解析了什么表，有多少个字段
        //log.info("generated table :{} , size :{}",classInfo.getTableName(),(classInfo.getFieldList() == null ? "" : classInfo.getFieldList().size()));

        //3.generate the code by freemarker templates with parameters . Freemarker根据参数和模板生成代码
        Map<String, String> result = generatorService.getResultByParams(dbDir, type, paramInfo.getOptions());
        result.put("className", classInfo.getClassName());
        return new JSONObject(result);
    }

    public static void main(String[] args) throws Exception {
        GeneratorController gen = new GeneratorController();
//        gen.generateCode("D:/llmdata", "table", "CREATE TABLE tbl_MasUserRoleUserAssignment (strUserName VARCHAR(20) NOT NULL, strUserRole VARCHAR(20) NOT NULL, strCreatedBy VARCHAR(20) NULL, dteCreatedOn TIMESTAMP NULL, strChangedBy VARCHAR(20) NULL, dteChangedOn TIMESTAMP NULL, CONSTRAINT PK_tbl_MasUserRoleUserAssignment PRIMARY KEY (strUserName, strUserRole))");
        gen.generateCode("D:/llmdata", "view", "CREATE VIEW v_project_detail AS SELECT ProjectID, Description, Manager1, Manager2, CutoffDay, LastCutoffDate, MonthlyResetDatetime, CreateBy, CreateDate, LastUpdBy, LastUpdDate, AutoEmailNotification");
//        gen.generateCode("D:/llmdata", "index", "AddNumbersFun;FnSplitStringFun");
//        gen.generateCode("D:/llmdata", "procedure", "proc_1;a character varying, IN b character varying, OUT result integer");
//        gen.generateCode("D:/llmdata", "function", "fun_2;");
//        gen.generateCode("D:/llmdata", "procedure", "sp_manage_sales;v_stor_id character, v_date timestamp without time zone, v_title_id character, v_qty smallint, v_discount double precision");
    }
}
